package com.itshare.video.service.impl;

import com.github.pagehelper.PageHelper;
import com.google.common.collect.Maps;
import com.itshare.video.common.core.constant.enums.ApiInfo;
import com.itshare.video.common.dto.PageEntity;
import com.itshare.video.common.dto.Result;
import com.itshare.video.common.dto.ViewObject;
import com.itshare.video.mapper.UserMapper;
import com.itshare.video.mapper.VideoCommentMapper;
import com.itshare.video.mapper.VideoMapper;
import com.itshare.video.mapper.custom.UserMapperCustom;
import com.itshare.video.mapper.custom.VideoCommentMapperCustom;
import com.itshare.video.mapper.custom.VideoMapperCustom;
import com.itshare.video.pojo.bo.VideoCreateBO;
import com.itshare.video.pojo.code.MessageType;
import com.itshare.video.pojo.code.PermitStatus;
import com.itshare.video.pojo.dto.UserTokenDTO;
import com.itshare.video.pojo.dto.VideoCommentDTO;
import com.itshare.video.pojo.po.User;
import com.itshare.video.pojo.po.UserMessage;
import com.itshare.video.pojo.po.Video;
import com.itshare.video.pojo.po.VideoComment;
import com.itshare.video.pojo.query.VideoQueryCondition;

import com.itshare.video.pojo.vo.VideoCommentVO;
import com.itshare.video.service.VideoService;
import com.itshare.video.util.MessageUtil;
import com.itshare.video.util.RedisKey;
import com.itshare.video.util.mapping.CommentDTOMapping;
import com.itshare.video.util.mq.UserMessageMq;
import lombok.extern.slf4j.Slf4j;
import org.mapstruct.factory.Mappers;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.SetOperations;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
* @Author lyr
* @create 2020/10/24 08:42
*/
@Slf4j
@Service
public class VideoServiceImpl implements VideoService {
    @Resource
    private VideoMapper videoMapper;
    @Resource
    private UserMapperCustom userMapperCustom;


    @Resource
    private VideoMapperCustom videoMapperCustom;

    @Resource
    private VideoCommentMapper videoCommentMapper;
    @Resource
    private VideoCommentMapperCustom videoCommentMapperCustom;

    @Resource
    private UserMessageMq userMessageMq;

    /**
     * 老师上传，并且发布了一个视频
     *
     * @param videoCreateBO
     * @return
     */
    @Override
    public Result<?> createVideoInfo(VideoCreateBO videoCreateBO) {
        Video video = new Video();
        //创建视频 并且插入数据库
        video.withCoverImageUrl(videoCreateBO.getCoverUrl())     //封面链接
                .withVideoMessage(videoCreateBO.getVideoMessage())  //视频描述内容
                .withVideoUrl(videoCreateBO.getVideoUrl())       //视频链接
                .withCategoryId(videoCreateBO.getCategoryId())  //视频分类ID
                .withChapterId(videoCreateBO.getVideoListId()) // 视频列表ID
                .withChapterTitle(videoCreateBO.getTitle())  //视频标题
                .withCreatedTime(new Date())
                .withUpdatedTime(new Date())

                .withUserId(videoCreateBO.getUserTokenDTO().getId())
                //首次创建视频，将数据库的统计字段设置为0
                .withCollectCount(0)
                .withCommentCount(0)
                .withLikeCount(0)
                .withLookCount(0);
        // videoCreateBO.setCreateTime(new Date());
        // videoCreateBO.setUpdateTime(new Date());
        int rows = videoMapper.insertSelective(video);
        if(rows<=0) {
            return Result.ofCode(ApiInfo.BASIC_ERROR)
                    .setMessage("未知异常，视频上传失败");
        }
        //丢到消息队列
        UserMessage userMessage = MessageUtil.getSysMsg(videoCreateBO.getUserTokenDTO());
        userMessageMq.sentMsg(userMessage);
        //上传成功，返回 video 视频ID
        return Result.ofCode(ApiInfo.OK)
                .setMessage("视频上传成功")
                .setData(video.getVideoId());
    }

    /**
     * 更新发布的视频信息
     *
     * @param videoCreateBO
     * @return
     */
    @Override
    public ViewObject updateVideoInfo(VideoCreateBO videoCreateBO) {
        UserTokenDTO userTokenDTO = videoCreateBO.getUserTokenDTO();
        Video video = new Video();
        //创建视频 并且插入数据库
        video.withCoverImageUrl(videoCreateBO.getCoverUrl())     //封面链接
                .withVideoMessage(videoCreateBO.getVideoMessage())  //视频描述内容
                .withVideoUrl(videoCreateBO.getVideoUrl())       //视频链接
                .withCategoryId(videoCreateBO.getCategoryId())  //视频分类ID
                .withChapterId(videoCreateBO.getVideoListId()) // 视频列表ID
                .withChapterTitle(videoCreateBO.getTitle())  //视频标题
                .withCreatedTime(new Date())
                .withUpdatedTime(new Date())
                .withVideoId(videoCreateBO.getPk())
                .withUserId(userTokenDTO.getId())
        ;

        videoMapper.updateByPrimaryKeySelective(video);
        return ViewObject.ofCode(ApiInfo.OK)
                .setMessage("视频信息更新成功");
    }

    /**
     * 获取用户个人发布的视频信息
     *
     * @param userTokenDTO
     * @param page
     * @param size
     * @return
     */
    @Override
    public Result<?> getUserVideoOfPublish(UserTokenDTO userTokenDTO, Integer page, Integer size) {
        PageHelper.startPage(page,size);
        VideoQueryCondition videoQueryCondition = VideoQueryCondition.builder()
                .userId(userTokenDTO.getId()).build();
        List<Video> list = videoMapperCustom.selectVideoByListByCondition(videoQueryCondition);
        return Result.ofCode(ApiInfo.OK)
                .setData(
                        PageEntity.of(list)
                );
    }


    /**
     * 按照查询条件进行搜索
     *
     * @param queryCondition
     * @return
     */
    @Override
    public Result<?> searchVideoBy(VideoQueryCondition queryCondition) {
        log.info("condition {}",queryCondition);
        List<Video> result = videoMapperCustom.selectVideoByListByCondition(queryCondition);
        PageHelper.startPage(queryCondition.getPage(),queryCondition.getSize());
        return Result.of(ApiInfo.OK)
                .setData(
                        PageEntity.of(result)
                )
                ;
    }

    @Resource
    private RedisTemplate<String, Object> redisTemplate;


    /**
     * 用户视频点赞
     *
     * @param videoId
     * @return
     */
    //TODO: 使用消息队列更新数据库
    @Override
    public Result<?> likeVideo(Integer videoId,Integer userId) {
        String videoSet = RedisKey.getLikeVideoKey(videoId);
        SetOperations<String,Object> ops = redisTemplate.opsForSet();
        Long row = ops.add(videoSet,userId);
        Map<String, Object> map = Maps.newHashMap();
        Result<Map<String, Object>> res = Result.ofCode(ApiInfo.OK);
        //异步更新 mysql数据库
        if(row==0){
            ops.remove(videoSet,userId);
            res.setMessage("取消点赞成功");
            //模仿b站，如果已经点赞了，就取消点赞
        }else{
            res.setMessage("点赞成功");
        }
        Long count = ops.size(videoSet);
        Video video = new Video();
        video.withVideoId(videoId.longValue())
                .withLikeCount(count.intValue());
        //发送视频消息
        userMessageMq.sendMsg(video);
        //更新视频
        map.put("like_count",count);
        return res
                .setData(map);

    }

    /**
     * 视频评论
     *
     * @param videoCommentDTO
     * @return
     */
    @Override
    public Result<?> commentVideo(VideoCommentDTO videoCommentDTO,Long videoId,UserTokenDTO userTokenDTO) {
        CommentDTOMapping mapping = Mappers.getMapper(CommentDTOMapping.class);
        VideoComment videoComment = mapping.from(videoCommentDTO);
        videoComment.setVideoId(videoId);
        log.info("userId {} ",userTokenDTO.getId());
        videoComment.setFromUserId( userTokenDTO.getId() );
        //插入评论
        User user = userMapperCustom.selectAvatarByPk(userTokenDTO.getId());
        videoComment.setFromAvatar(user.getAvatar());


        videoCommentMapper.insertSelective(videoComment);
        return Result.ofCode(ApiInfo.OK)
                .setData(videoCommentDTO);
    }

    /**
     * 返回评论列表
     *
     * @param videoId
     * @param page
     * @param size
     * @return
     */
    @Override
    public ViewObject getVideoComment(Integer videoId, Integer page, Integer size) {
        PageHelper.startPage(page,size);
        // List<VideoComment> videoComments = videoCommentMapper
        List<VideoComment> res = videoCommentMapperCustom.getVideoComment(videoId);
        PageEntity<VideoComment> videoPageEntity = PageEntity.of(res);
        List<VideoCommentVO> vos = videoPageEntity.getList()
                .stream()
                .map(videoComment -> {
                    VideoCommentVO videoCommentVO = new VideoCommentVO();
                    videoCommentVO.setVideoComment(videoComment);
                    return videoCommentVO;
                })
                .peek(videoCommentVO -> {
                    PageHelper.startPage(1,4);
                    VideoComment parent = videoCommentVO.getVideoComment();
                    //获取二级评论, 二级评论获取4条，懒加载
                    List<VideoComment> childList = videoCommentMapperCustom.getVideoCommentLevel2(videoId, parent.getCommentId().intValue());
                    videoCommentVO.setChilds(PageEntity.of(childList));
                })
                .collect(Collectors.toList());

        return ViewObject.of(ApiInfo.OK)
                .put("commentList",vos);
    }

    /**
     * 获取子评论
     *
     * @param parentCommentId
     * @param videoId
     * @param page
     * @param size
     * @return
     */
    @Override
    public Result<PageEntity<VideoComment>> getVideoCommentChilds(Integer parentCommentId, Integer videoId, Integer page, Integer size) {
        List<VideoComment> res = videoCommentMapperCustom.getVideoCommentLevel2(videoId,parentCommentId);
        return Result.<PageEntity<VideoComment>>of(ApiInfo.OK)
                .setData(PageEntity.of(res));
    }

    /**
     * 获取视频 根据ID
     *
     * @param videoId
     * @return
     */
    @Override
    public Result<Video> getVideoById(Long videoId) {
        return Result.<Video>of(
                ApiInfo.OK
        ).setData(videoMapper.selectByPrimaryKey(videoId));
    }

    /**
     * 逻辑删除视频
     *
     * @param videoId
     * @return
     */
    @Override
    public Result<?> logicDeleteVideo(Integer videoId) {
        Video video = videoMapper.selectByPrimaryKey(videoId.longValue());
        //逻辑删除
        video.setDeleteStatus(1);
        //视频审核不通过
        video.setPermitStatus(PermitStatus.no_permit.type);
        //更新
        videoMapper.updateByPrimaryKeySelective(video);
        UserMessage userMessage = MessageUtil.setVideoDelete(videoId)
                .withToUserMessage("您的视频有违法信息，已经被管理员下架")
                .withFeedbackTitle("视频下架通知")
                 ;
        //发送消息
        userMessageMq.sentMsg(userMessage);
        return Result.of(ApiInfo.OK);
    }


    /**
     * 获取所有被举报了的视频
     *
     * @return
     */
    @Override
    public Result<?> getAllVideoBeReported(Integer page,Integer size) {
        PageHelper.startPage(page,size);
        //获取被举报了的视频
        List<Video> result = videoMapperCustom.listVideoWhereBeReported();
        return Result.of(ApiInfo.OK)
                .setData(
                        PageEntity.of(result)
                );
    }
}
